package com.linked.universal.linkedutil;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * @author Bluerain
 * @version 1.0
 * @data 2025/4/24 13:55
 * @describe 对称加密中的AES加密
 */
public class AESUtils {


    private static final String ALGORITHM = "AES";
    private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
    /**
     * 128位(16字节)
     * 192位(24字节)
     * 256位(32字节)
     */
    private static final int KEYSIZE = 128;
    // AES块大小是16字节
    private static final int IV_SIZE = 16;

    public static void main(String[] args) throws Exception {
        String plainText = "这是要加密的敏感数据";

        String secretKey = "1234567890123456";
        System.out.println("AES密钥: " + secretKey + " length: " + secretKey.length());
        // String secretKey = "1234567890123456"; // 必须16/24/32字节

        // 加密
        EncryptionResult result = encrypt(plainText, secretKey);
        System.out.println("加密结果: " + result.encryptedText);
        System.out.println("IV向量: " + result.iv);

        // 解密
        String decrypted = decrypt(result.encryptedText, secretKey, result.iv);
        System.out.println("解密结果: " + decrypted);
    }

    /**
     * 生成得密钥不能被转为String
     * */
    @Deprecated
    public static String generateRandomKey() throws NoSuchAlgorithmException {
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        // 可以是128, 192或256
        keyGen.init(KEYSIZE, new SecureRandom());
        SecretKey secretKey = keyGen.generateKey();
        return Base64.getEncoder().encodeToString(secretKey.getEncoded());
    }

    /**
     * @param plainText 要加密得文本
     * @param secretKey 对称密钥
     * @return 加密结果 {加密结果，IV向量}
     * @deprecated AES-CBC加密接口
     */
    public static EncryptionResult encrypt(String plainText, String secretKey) throws Exception {
        // 生成随机IV
        byte[] iv = new byte[IV_SIZE];
        new SecureRandom().nextBytes(iv);
        IvParameterSpec ivSpec = new IvParameterSpec(iv);

        // 创建密钥
        SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), ALGORITHM);

        // 初始化加密器
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);

        // 加密
        byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));

        // 返回加密结果和IV(需要Base64编码)
        return new EncryptionResult(
                Base64.getEncoder().encodeToString(encryptedBytes),
                Base64.getEncoder().encodeToString(iv)
        );
    }

    /**
     * @param encryptedText 加密后文本
     * @param secretKey     对称密钥
     * @param iv            初始化向量
     * @return 解密结果
     * @deprecated AES-CBC解密接口
     */
    public static String decrypt(String encryptedText, String secretKey, String iv) throws Exception {
        // 解码IV
        byte[] ivBytes = Base64.getDecoder().decode(iv);
        IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);

        // 创建密钥
        SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), ALGORITHM);

        // 初始化解密器
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);

        // 解密
        byte[] encryptedBytes = Base64.getDecoder().decode(encryptedText);
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);

        return new String(decryptedBytes, StandardCharsets.UTF_8);
    }

    /**
     * 加密结果实体类
     */
    static class EncryptionResult {
        public final String encryptedText;
        public final String iv;

        public EncryptionResult(String encryptedText, String iv) {
            this.encryptedText = encryptedText;
            this.iv = iv;
        }
    }
}
